package edu.cmu.cs.cs214.hw9.server;

import java.io.*;
import java.net.*;

/**
 * Implements a database shard.
 */
public class Server {
	private ServerSocket socket;
	public static String USAGE_MSG = "Usage: server <port, 1-65535>";
	
	/**
	 * Closes a socket. Put in for readability.
	 *  
	 * @param s Socket to close.
	 */
	private void closeSocket(Socket s) {
		try {
			s.close();
		} catch (IOException e) {
			System.err.println("Could not close socket: " + e.getMessage());
		}
	}
	
	/**
	 * Closes a Reader. Put in for readability.
	 *  
	 * @param r Reader to close.
	 */
	private void closeReader(Reader r) {
		try {
			r.close();
		} catch (IOException e) {
			System.err.println("Could not close reader: " + e.getMessage());
		}
	}
	
	/**
	 * Spawns an instance of the server.
	 * 
	 * @param port Port to listen on.
	 */
	public Server(int port) {
		try {
			socket = new ServerSocket(port);
		} catch (IOException e) {
			System.err.println("Could not bind to port " + port + ": " + e.getMessage());
			System.exit(1);
		}
		
		while (true) {
			// Handles for reading and writing to client.
			Socket client = null;
			BufferedReader in = null;
			PrintWriter out = null;

			try {
				client = socket.accept();
			} catch (IOException e) {
				System.err.println("Could not accept connection from client:" + e.getMessage());
				continue;
			}
			
			try {
				// Used to get data from the client.
				in = new BufferedReader(new InputStreamReader(client.getInputStream()));
				
				// Used to send the client a reply indicating whether their request was successful or not.
				out = new PrintWriter(client.getOutputStream(), true);
			} catch (IOException e) {
				System.err.println("Could not interface with client:" + e.getMessage());
				closeSocket(client);
				continue;
			}
			
			try {
				// Read client data.
			} catch (IOException e) {
				System.err.println("Could not read data from client:" + e.getMessage());
				out.close();
				closeReader(in);
				closeSocket(client);
				continue;
			}
				
			// Cleanup
			out.close();
			closeReader(in);
			closeSocket(client);
		}
	}
	
	/**
	 * Parses a port number from a string.
	 * (I.e. s is numeric and 1 <= s <= 65535)
	 *  
	 * @param s String to test.
	 * @return port number if valid port; 0 otherwise.
	 */
	public static int getPort(String s) {
		try {
			int num = Integer.parseInt(s);
			if (1 <= num && num <= 65535) return num;
			
			return 0;
		} catch (NumberFormatException e) {
			return 0;
		}
	}
	
	public static void main(String[] args) {
//		// Get port number
//		if (args.length == 0 || args.length > 2) {
//			System.out.printf(USAGE_MSG);
//			System.exit(1);
//		}
//		
//		int port = getPort(args[0]);
//		if (port == 0) {
//			System.out.printf(USAGE_MSG);
//			System.exit(1);
//		}
//		
		// Start 2 shards, on port 5000 and 5001.
		new Server(5000);
		new Server(5001);
	}
}
